var __importDefault =
    (this && this.__importDefault) ||
    ((mod) => (mod?.__esModule ? mod : { default: mod }));
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProxyFunctionInliner = void 0;
const transformation_1 = require("../transformation");
const traverse_1 = __importDefault(require("@babel/traverse"));
const variable_1 = require("../../helpers/variable");
const proxyFunction_1 = require("./proxyFunction");
const misc_1 = require("../../helpers/misc");
class ProxyFunctionInliner extends transformation_1.Transformation {
    /**
     * Executes the transformation.
     * @param log The log function.
     * @returns Whether any changes were made.
     */
    execute(_log) {
        const usages = [];
        let depth = 0;
        (0, traverse_1.default)(this.ast, {
            enter(path) {
                (0, misc_1.setProperty)(path, "depth", depth++);
                const variable = (0, variable_1.findConstantVariable)(
                    path,
                    proxyFunction_1.isProxyFunctionExpression,
                    true,
                );
                if (!variable) {
                    return;
                }
                const proxyFunction = new proxyFunction_1.ProxyFunctionVariable(
                    variable,
                );
                usages.push(
                    ...proxyFunction.getCalls().map((p) => [p, proxyFunction]),
                );
            },
        });
        // replace innermost proxy calls first
        usages.sort(
            (a, b) =>
                (0, misc_1.getProperty)(b[0], "depth") -
                (0, misc_1.getProperty)(a[0], "depth"),
        );
        for (const [path, proxyFunction] of usages) {
            if (proxyFunction.replaceCall(path)) {
                this.setChanged();
            }
        }
        return this.hasChanged();
    }
}
exports.ProxyFunctionInliner = ProxyFunctionInliner;
ProxyFunctionInliner.properties = {
    key: "proxyFunctionInlining",
    rebuildScopeTree: true,
};
